/**
 *
 */
package com.naiterui.ehp.bp.utils.notice;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.naiterui.ehp.bp.support.exception.BusinessException;
import com.naiterui.ehp.bp.support.utils.JsonMapper;
import com.naiterui.ehp.bp.utils.net.RestHttpUtil;

import lombok.Getter;
import lombok.Setter;

/**
 * App通知消息工具类
 * @author Gaoll
 * @since HZD-1.0.0
 */
public class AppNoticeUtil {

    /**
     * 日志对象：<code>LOGGER</code>
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(AppNoticeUtil.class);

    /**
     * 单人-通知类消息：<code>SINGLE_SEND</code>
     */
    private static final String SINGLE_SEND = "/send/single/";
    /**
     * 群发-通知类消息：<code>BATCH_SEND</code>
     */
    private static final String BATCH_SEND = "/send/batch/";

    /**
     * 单人-通知类消息
     * AppNoticeUtil.sendSingleNotice()
     *
     * @param userId
     * @param noticeType
     * @param noticeInfo
     *
     * @return
     *
     * @throws BusinessException
     * @Author Gaoll
     * @Date 2016年8月5日
     * @since HZD-1.0.0
     */
    public static boolean sendSingleNotice(String host, Long userId, NoticeType noticeType, CommonNotice noticeInfo) throws BusinessException {

        String type = noticeType.type;
        Class infoClazz = noticeType.clazz;

        if (null == noticeInfo || !noticeInfo.getClass().equals(infoClazz)) {

            LOGGER.error("sendBatchNotice ERROR ; illegal param : infoClass={},infoValue={}",
                         null == noticeInfo ? "NULL" : noticeInfo.getClass().getName(), null == noticeInfo ? "NULL" : noticeInfo.toString());
            return false;
        }
        LOGGER.debug("sendSingleNotice params : userId={},noticeType={},noticeInfo={}", userId, noticeType, noticeInfo);

        String callUrl = host.concat(SINGLE_SEND).concat(type);
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("userId", userId.toString());
        paramMap.put("info", noticeInfo.toString());
        RestHttpUtil.post().url(callUrl).paramMap(paramMap).executeData();

        LOGGER.info("sendSingleNotice SUCCESS : userId={},noticeType={},noticeInfo={}", userId, noticeType, noticeInfo.toString());
        return true;
    }

    /**
     * 单人-通知类消息
     * AppNoticeUtil.sendSingleNotice()
     *
     * @param userId
     * @param noticeType
     * @param noticeInfo
     *
     * @return
     *
     * @throws BusinessException
     * @Author Gaoll
     * @Date 2016年8月5日
     * @since HZD-1.0.0
     */
    public static boolean sendBatchNotice(String host, NoticeType noticeType, CommonNotice noticeInfo) throws BusinessException {

        String type = noticeType.type;
        Class infoClazz = noticeType.clazz;

        if (null == noticeInfo || !noticeInfo.getClass().equals(infoClazz)) {

            LOGGER.error("sendBatchNotice ERROR ; illegal param : infoClass={},infoValue={}",
                    null == noticeInfo ? "NULL" : noticeInfo.getClass().getName(), null == noticeInfo ? "NULL" : noticeInfo.toString());
            return false;
        }
        LOGGER.debug("sendBatchNotice params : noticeType={},noticeInfo={}", noticeType, noticeInfo);

        String callUrl = host.concat(BATCH_SEND).concat(type);
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("info", noticeInfo.toString());
        RestHttpUtil.post().url(callUrl).paramMap(paramMap).executeData();

        LOGGER.info("sendBatchNotice SUCCESS : noticeType={},noticeInfo={}", noticeType, noticeInfo.toString());
        return true;
    }

    /**
     * APP通知类消息Type
     *
     * @author Gaoll
     * @since HDZ-1.0.0
     */
    @Getter
    public enum NoticeType {

        // ---------------------------医生APP通知类消息-------------------------------//
        DR_NEW_PATIENT("newPatient", NewPatient.class),
        DR_NOTICE_INFO("noticeInfo", NoticeInfo.class),
        DR_DYNAMIC_INFO("dynamicInfo", DrDynamicInfo.class),
        DR_ANSWER_REQUIRE("answerRequire", AnswerRequire.class),
        DR_RESERVATION_MIND("reservationRemind", ReservationMind.class),
        DR_LEGAL_STATUS("legalStatus", LegalStatus.class),
        DR_REVISIT("revisit", Revisit.class),
        DR_NEW_REQUIRE("newRequire", NewRequire.class),
        DR_VIDEO_CONSULT("videoConsult", VideoConsult.class),
        DR_VIDEO_CONSULT_IMAGE("videoConsultDrImage", VideoConsultImage.class),
        PT_VIDEO_CONSULT_IMAGE("videoConsultPtImage", VideoConsultImage.class),

        // ---------------------------经纪人APP通知类消息-------------------------------//
        AG_SYS_NOTICE("sysNotice", SimpleNotice.class),
        AG_AUTH_NOTICE("authNotice", SimpleNotice.class),
        AG_NEW_CUSTOM("newCustom", SimpleNotice.class),
        AG_CHANGE_AREA_MANAGE("changeAreaManage", SimpleNotice.class);


        /**
         * 通知消息类型：<code>type</code>
         */
        private String type;
        /**
         * 通知消息VO：<code>clazz</code>
         */
        private Class clazz;

        <T> NoticeType(String type, Class<T> clazz) {
            this.type = type;
            this.clazz = clazz;
        }

    }

    // ==============================通知消息格式Bean==============================//

    /**
     * 通知类消息公共类
     *
     * @author Gaoll
     * @since HZD-1.0.0
     */
    abstract static class CommonNotice implements Serializable {

        /**
         * 字段或域定义：<code>serialVersionUID</code>
         */
        private static final long serialVersionUID = -8530702733573410203L;

        /**
         * @return
         *
         * @Author Gaoll
         * @Date 2016年8月5日
         * @see java.lang.Object#toString()
         * @since HZD-1.0.0
         */
        @Override
        public String toString() {
            return JsonMapper.toJson(this);
        }

    }

    /**
     * 医生APP-新患者通知
     *
     * @author Gaoll
     * @since HZD-1.0.0
     */
    public static class NewPatient extends CommonNotice {

        /**
         * 字段或域定义：<code>serialVersionUID</code>
         */
        private static final long serialVersionUID = 4182822168600092795L;

        private Long patientId;

        /**
         * 构造函数
         *
         * @param patientId
         */
        public NewPatient(Long patientId) {
            super();
            this.patientId = patientId;
        }

        @Override
        public String toString() {
            return this.patientId.toString();
        }
    }

    /**
     * 医生APP-当日复诊提醒
     */
    @Getter
    public static class Revisit extends CommonNotice {

        private static final long serialVersionUID = 4999771595181781287L;
        private Integer count;

        /**
         * 构造函数
         *
         * @param count
         */
        public Revisit(Integer count) {
            super();
            this.count = count;
        }

        @Override
        public String toString() {
            return this.count.toString();
        }

    }


    /**
     * 医生APP-新的求药通知
     */
    @Getter
    @Setter
    public static class NewRequire extends CommonNotice {

        private static final long serialVersionUID = 476577439048993809L;
        private String message;

        /**
         * 构造函数
         *
         * @param message
         */
        public NewRequire(String message) {
            super();
            this.message = message;
        }


        @Override
        public String toString() {
            return this.message;
        }

    }

    /**
     * 医生APP-公告通知
     *
     * @author Gaoll
     * @since HZD-1.0.0
     */
    @Getter
    public static class NoticeInfo extends CommonNotice {

        /**
         * 字段或域定义：<code>serialVersionUID</code>
         */
        private static final long serialVersionUID = 7109649982312090294L;

        String content;
        Long time;
        String linkUrl;
        String headImg;
        Long topic;
        String title;

        /**
         * 构造函数
         */
        public NoticeInfo(String content, Long time, String linkUrl, String headImg, Long topic, String title) {
            super();
            this.content = content;
            this.time = time;
            this.linkUrl = linkUrl;
            this.headImg = headImg;
            this.topic = topic;
            this.title = title;
        }

    }

    /**
     * 医生APP-账户动态
     *
     * @author Gaoll
     * @since 2.9.0
     */
    @Getter
    public static class DrDynamicInfo extends CommonNotice {

        /**
         * 字段或域定义：<code>serialVersionUID</code>
         */
        private static final long serialVersionUID = -4571303759307849986L;

        String content;
        Long time;
        String linkUrl;
        String headImg;
        @JsonInclude(Include.NON_NULL)
        Integer status;
        @JsonInclude(Include.NON_NULL)
        Integer recordStatus;

        public DrDynamicInfo(String content, Long time, String linkUrl, String headImg) {
            super();
            this.content = content;
            this.time = time;
            this.linkUrl = linkUrl;
            this.headImg = headImg;
        }

        /**
         * 构造函数
         *
         * @param content
         * @param time
         * @param linkUrl
         * @param headImg
         * @param status       认证状态
         * @param recordStatus 备案状态
         */
        public DrDynamicInfo(String content, Long time, String linkUrl, String headImg, Integer status, Integer recordStatus) {
            super();
            this.content = content;
            this.time = time;
            this.linkUrl = linkUrl;
            this.headImg = headImg;
            this.status = status;
            this.recordStatus = recordStatus;
        }

    }

    /**
     * 医生APP-在线视频咨询状态变更通知
     *
     * @author Gaoll
     * @since HZD-1.0.0
     */
    @Getter
    public static class ReservationMind extends CommonNotice {
        /**
         * 字段或域定义：<code>serialVersionUID</code>
         */
        private static final long serialVersionUID = -6839017184279191990L;

        Long patientId;
        Long reservationId;
        Integer reservationStatus;

        /**
         * 构造函数
         *
         * @param patientId
         * @param reservationId
         * @param reservationStatus
         */
        public ReservationMind(Long patientId, Long reservationId, Integer reservationStatus) {
            super();
            this.patientId = patientId;
            this.reservationId = reservationId;
            this.reservationStatus = reservationStatus;
        }

    }

    /**
     * 医生APP-购药咨询系统自动确认
     *
     * @author Gaoll
     * @since HZD-1.0.0
     */
    @Getter
    public static class AnswerRequire extends CommonNotice {
        /**
         * 字段或域定义：<code>serialVersionUID</code>
         */
        private static final long serialVersionUID = -2456936824526068273L;

        String sessionId;
        Long endTime;
        Long fromId;
        Long toId;
        Integer relation;
        Long time;
        Long requireId;
        Long recommedId;

        /**
         * 构造函数
         */
        public AnswerRequire(String sessionId, Long endTime, Long fromId, Long toId, Integer relation, Long time, Long requireId, Long recommedId) {
            super();
            this.sessionId = sessionId;
            this.endTime = endTime;
            this.fromId = fromId;
            this.toId = toId;
            this.relation = relation;
            this.time = time;
            this.requireId = requireId;
            this.recommedId = recommedId;
        }

    }

    /**
     * 医生APP-医生核发备案状态变更通知
     *
     * @author Gaoll
     * @since HZD-1.0.0
     */
    public static class LegalStatus extends CommonNotice {

        public static final int STATUS_TYPE_LEGAL = 1;
        public static final int STATUS_TYPE_ILLEGAL = 2;

        /**
         * 字段或域定义：<code>serialVersionUID</code>
         */
        private static final long serialVersionUID = -6204428057616808283L;

        Integer recordStatus;

        /**
         * 构造函数
         *
         * @param recordStatus
         */
        public LegalStatus(Integer recordStatus) {
            super();
            this.recordStatus = recordStatus;
        }

        /**
         * @return Integer 取得域 recordStatus 的方法。
         */
        public Integer getRecordStatus() {
            return this.recordStatus;
        }

        @Override
        public String toString() {
            return this.recordStatus.toString();
        }
    }

    /**
     * 医生APP-视频问诊通知
     */
    @Getter
    @Setter
    public static class VideoConsult extends CommonNotice {
        /**
         * 添加待接诊
         */
        public static final int OPERATE_ADD = 1;

        /**
         * 减少待接诊
         */
        public static final int OPERATE_REDUCE = 2;

        private static final long serialVersionUID = -2519406247116807616L;
        private Integer operate;

        /**
         * 构造函数
         *
         * @param operate
         */
        public VideoConsult(Integer operate) {
            super();
            this.operate = operate;
        }


        @Override
        public String toString() {
            return this.operate.toString();
        }

    }

    /**
     * 视频问诊发送发图片
     */
    @Getter
    @Setter
    public static class VideoConsultImage extends CommonNotice {

        private static final long serialVersionUID = -3100328625012817854L;

        /**
         * 内容
         */
        private String content;

        /**
         * 构造函数
         *
         * @param content
         */
        public VideoConsultImage(String content) {
            super();
            this.content = content;
        }
    }

    /**
     * 简单消息
     */
    @Getter
    public static class SimpleNotice extends CommonNotice {

        /**
         * 字段或域定义：<code>serialVersionUID</code>
         */
        private static final long serialVersionUID = 7109649982312090294L;

        String content;
        String title;
        Long time;
        String type;

        /**
         * 构造函数
         */
        public SimpleNotice(String title, String content, Long time) {
            super();
            this.title = title;
            this.content = content;
            this.time = time;
        }

    }
}
